package com.zhiyou.Reflection;

import org.junit.Test;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class ReflectionTest {
    //反射之前,对于 Person 的操作
    @Test
    public void test1(){

        //1.创建Person类的对象
        Person p1 = new Person("tom",12);

        //2.通过对象,调用其内部的属性,方法
        p1.age = 10;
        System.out.println(p1.toString());
        p1.show();

        //在Person 类的外部 ,我们是不可以通过Person类的对象调用其内部私有的结构.
        //比如name,showNation()以及私有的构造器
    }
    //反射之后,对于 Person 的操作
    @Test
    public void test2() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
        Class clazz = Person.class;
        Constructor cons = clazz.getConstructor(String.class, int.class);

        Object obj = cons.newInstance("tom", 12);
        Person p = (Person) obj;
        System.out.println(p.toString());
        //2.通过反射,调用对象指定的属性,方法
        Field age = clazz.getDeclaredField("age");
        age.set(p,10);
        System.out.println(p.toString());

        Method show = clazz.getDeclaredMethod("show");
        show.invoke(p);

        System.out.println("+++++++++++++++++++++++++++++++++++++++++++++++");

        //通过反射,是可以调用Person类的私有结构的.比如 私有的构造器,方法,属性
        Constructor cons1 = clazz.getDeclaredConstructor(String.class);
        cons1.setAccessible(true);
        Person p1 = (Person) cons1.newInstance("Jarry");
        System.out.println(p1);

        //调用私有的属性
        Field name = clazz.getDeclaredField("name");
        name.setAccessible(true);
        name.set(p1,"hanmeimei");

        //调用私有的方法
        Method showNation = clazz.getDeclaredMethod("showNation", String.class);
        showNation.setAccessible(true);
        String nation = (String)showNation.invoke(p1, "中国");
        System.out.println(nation);
    }
}
